Introduction to Errors and Exceptions in Python
Course: Python Training
Topic: Introduction to Errors and Exceptions in Python
Course Link: Python Training Course
Demo Link: Register for a Course Demo
Website: JustAcademy
1. Introduction
Errors and exceptions are important concepts in Python programming. They help developers identify problems in source code, understand unexpected program behavior, and build applications that handle failures gracefully.
An error may occur because of incorrect syntax, invalid operations, missing resources, unexpected input, or violations of application rules. Understanding these problems helps programmers write reliable, maintainable, and user-friendly applications.
Python provides several mechanisms for handling exceptions, including try, except, else, finally, and raise. These mechanisms allow a program to respond to expected failures instead of terminating unexpectedly.
For example, a calculator should handle division by zero, a registration form should validate user input, and a file-processing application should respond appropriately when a file cannot be opened.
2. Learning Objectives
- Understand the meaning of errors and exceptions in Python.
- Differentiate syntax errors, runtime errors, and logical errors.
- Identify common built-in Python exceptions.
- Understand how Python reports errors using tracebacks.
- Handle exceptions using
try and except.
- Use multiple exception handlers effectively.
- Understand the purpose of
else and finally.
- Raise exceptions using the
raise statement.
- Apply error-handling techniques in practical programs.
3. What Is an Error in Python?
An error is a problem that prevents a program from behaving as intended. Depending on the situation, Python may reject the code before execution, raise an exception during execution, or execute the code successfully while producing an incorrect result.
Example
number = 10
divisor = 0
result = number / divisor
print(result)
Result: Python raises a ZeroDivisionError because a number cannot be divided by zero.
Errors can arise from several sources, including:
- Incorrect Python syntax.
- Invalid data types or values.
- Missing variables or functions.
- Invalid mathematical operations.
- Missing files or unavailable resources.
- Incorrect business logic.
4. Types of Errors in Python
Python programming problems are commonly classified into syntax errors, runtime exceptions, and logical errors. These categories describe different ways a program can fail or produce incorrect results.
4.1 Syntax Errors
A syntax error occurs when Python cannot parse code because it violates the language's grammar. The program cannot execute normally until the syntax problem is corrected.
Example:
if 10 > 5
print("Ten is greater")
Error:
SyntaxError: expected ':'
The problem is the missing colon after the condition.
Correct code:
if 10 > 5:
print("Ten is greater")
Output:
Ten is greater
4.2 Runtime Errors and Exceptions
A runtime exception occurs when Python encounters a problem while executing a statement. The statement may be syntactically correct but impossible to complete under the current conditions.
Example:
number = 10
divisor = 0
print(number / divisor)
Error:
ZeroDivisionError: division by zero
The code follows valid Python syntax, but the division operation is invalid.
4.3 Logical Errors
A logical error occurs when a program runs without necessarily raising an exception but produces an incorrect result because the algorithm or calculation is wrong.
Example:
length = 10
width = 5
area = length + width
print("Area:", area)
Output:
Area: 15
The program executes successfully, but the formula for the area of a rectangle should multiply the length by the width.
Correct code:
length = 10
width = 5
area = length * width
print("Area:", area)
Output:
Area: 50
Comparison of Error Types
| Error Type |
When It Occurs |
Example |
How to Fix It |
| Syntax error |
When Python cannot parse the code. |
Missing colon after an if statement. |
Correct the syntax. |
| Runtime exception |
When an operation fails during execution. |
Dividing by zero. |
Handle the exception or correct the operation. |
| Logical error |
When code runs but gives an incorrect result. |
Adding dimensions instead of multiplying them. |
Correct the algorithm or formula. |
5. What Is an Exception?
An exception is an object that represents an abnormal condition encountered during program execution. Python raises an exception when an operation cannot proceed normally.
Examples include:
- Dividing a number by zero.
- Converting invalid text into an integer.
- Accessing a variable that has not been defined.
- Opening a file that does not exist.
- Accessing an invalid list index.
Example: ValueError
age = int("twenty")
print(age)
Error:
ValueError: invalid literal for int() with base 10: 'twenty'
The int() function cannot convert the text "twenty" into an integer. Because the exception is not handled, program execution stops at that point.
6. Understanding Common Built-in Exceptions
Python includes many built-in exception classes. Each class represents a particular category of failure, allowing developers to handle different problems appropriately.
| Exception |
Description |
Example |
SyntaxError |
Invalid Python syntax. |
if True print("Hi") |
IndentationError |
Incorrect indentation. |
An improperly indented statement. |
NameError |
A name is not defined in the current scope. |
print(username) when the name is undefined. |
TypeError |
An operation or function receives an inappropriate type. |
"Age: " + 20 |
ValueError |
A value has an inappropriate format or content. |
int("hello") |
ZeroDivisionError |
A division or modulo operation uses zero as its divisor. |
10 / 0 |
IndexError |
A sequence index is out of range. |
[1, 2][5] |
KeyError |
A dictionary key does not exist. |
{"name": "Riya"}["age"] |
AttributeError |
An object does not provide the requested attribute. |
Calling a nonexistent method. |
FileNotFoundError |
A requested file cannot be found. |
Opening a missing file. |
ImportError |
An import operation fails. |
Importing an unavailable name. |
ModuleNotFoundError |
A requested module cannot be found. |
Importing a module that is not installed or available. |
OverflowError |
A numeric operation exceeds a supported range for that operation. |
Some floating-point or mathematical operations. |
7. Understanding Python Tracebacks
A traceback is the diagnostic information Python displays when an exception is not handled. It usually shows the sequence of calls that led to the error, source file names, line numbers, and the exception type and message.
Example
def calculate():
number = 10
divisor = 0
return number / divisor
calculate()
Typical final traceback line:
ZeroDivisionError: division by zero
When reading a traceback, focus on the following details:
- Exception type: Identifies the category of problem.
- Error message: Explains the immediate failure.
- File and line number: Identifies where the exception occurred.
- Function call sequence: Shows how execution reached the failing statement.
Tracebacks are particularly useful when debugging applications with several functions or modules.
8. Introduction to Exception Handling
Exception handling allows a program to respond to errors without necessarily terminating immediately. Python uses a try block to identify statements that may fail and an except block to handle specified exceptions.
Basic Syntax
try:
# Code that may raise an exception
statement
except ExceptionType:
# Handle the specified exception
recovery_statement
Example: Handling Division by Zero
try:
number = 10
divisor = 0
result = number / divisor
print(result)
except ZeroDivisionError:
print("Cannot divide by zero.")
Output:
Cannot divide by zero.
When a ZeroDivisionError occurs, Python skips the remaining statements in the try block and executes the matching except block.
9. Using Multiple Except Blocks
A program may encounter different types of exceptions. Multiple except blocks allow it to respond differently depending on which exception occurs.
Example
try:
number = int(input("Enter a number: "))
result = 100 / number
print("Result:", result)
except ValueError:
print("Please enter a valid integer.")
except ZeroDivisionError:
print("The number cannot be zero.")
Possible outputs:
Enter a number: abc
Please enter a valid integer.
Or:
Enter a number: 0
The number cannot be zero.
Only the matching handler executes for an exception raised within the protected try block. Handling specific exceptions makes the program easier to understand and maintain.
10. Capturing Exception Messages
You can capture an exception object using as in an except clause. This allows the program to display, log, or inspect the exception message.
Example
try:
result = 10 / 0
except ZeroDivisionError as error:
print("An error occurred:", error)
Output:
An error occurred: division by zero
Using the exception object can provide useful diagnostic information. In production applications, avoid exposing sensitive internal details to end users; detailed diagnostics should generally be recorded in appropriate logs.
11. Using the else Clause
The else clause executes only when the try block completes without raising an exception handled by its associated handlers.
Example
try:
number = int("25")
except ValueError:
print("Invalid number.")
else:
print("Conversion successful.")
print("Number:", number)
Output:
Conversion successful.
Number: 25
The else clause keeps successful-operation code separate from the statements that need exception handling. This reduces the risk of accidentally catching errors from unrelated operations.
12. Using the finally Clause
The finally clause runs when control leaves the associated try statement, whether an exception occurred or not. It is commonly used for cleanup tasks such as releasing resources.
Example
try:
number = 10
divisor = 0
print(number / divisor)
except ZeroDivisionError:
print("Division error occurred.")
finally:
print("Execution of the try statement is complete.")
Output:
Division error occurred.
Execution of the try statement is complete.
The finally block executes even though the division operation raises an exception.
Important: Avoid returning from a finally block because doing so can suppress an exception or override an earlier return value. For file handling, Python's with statement is often the preferred way to manage resource cleanup.
13. Using try, except, else, and finally Together
These clauses can be combined to provide a complete exception-handling structure.
Example
try:
number = int(input("Enter a number: "))
result = 100 / number
except ValueError:
print("Invalid input. Enter an integer.")
except ZeroDivisionError:
print("Zero is not allowed.")
else:
print("Calculation successful.")
print("Result:", result)
finally:
print("Program operation completed.")
Example output for input 20:
Enter a number: 20
Calculation successful.
Result: 5.0
Program operation completed.
Purpose of each clause:
| Clause |
Purpose |
try |
Contains statements that may raise exceptions. |
except |
Handles matching exceptions. |
else |
Runs when the try block succeeds without an exception. |
finally |
Runs during normal exit from the construct, including when an exception occurs. |
14. Raising Exceptions Manually
The raise statement allows developers to signal an exception when a condition violates the requirements of an operation.
Example: Validating Age
age = -5
if age < 0:
raise ValueError("Age cannot be negative")
print("Age:", age)
Result: Python raises ValueError with the message Age cannot be negative.
Raising an exception is useful when a function detects invalid input or cannot safely continue. The exception can be handled by the function's caller when appropriate.
15. Re-Raising an Exception
Sometimes a program needs to perform an action when an exception occurs but still allow the original exception to propagate. The raise statement without an argument re-raises the currently handled exception.
Example
try:
number = int("hello")
except ValueError:
print("Logging invalid input.")
raise
The program prints the logging message and then re-raises the original ValueError. If no outer handler catches it, the exception remains unhandled.
This technique is useful when a function needs to record or add context to a failure without pretending that the operation succeeded.
16. Exception Hierarchy in Python
Python exceptions are organized into an inheritance hierarchy. At the top is BaseException, from which the main Exception class and several special termination-related exceptions derive.
Most application errors inherit from Exception. Exceptions such as KeyboardInterrupt and SystemExit are not subclasses of Exception, so they are not normally caught by an except Exception handler.
Simplified Hierarchy
BaseException
|
+-- Exception
| |
| +-- ArithmeticError
| | +-- ZeroDivisionError
| | +-- OverflowError
| |
| +-- LookupError
| | +-- IndexError
| | +-- KeyError
| |
| +-- TypeError
| +-- ValueError
| +-- OSError
| +-- FileNotFoundError
|
+-- KeyboardInterrupt
+-- SystemExit
This is a simplified illustration, not a complete list of Python's exception classes. Understanding inheritance helps developers choose appropriate handlers and create custom exception hierarchies.
17. Catching Multiple Exception Types Together
When several exception types require the same response, they can be grouped in a tuple inside an except clause.
Example
try:
value = int(input("Enter a number: "))
result = 100 / value
except (ValueError, ZeroDivisionError) as error:
print("Input or calculation error:", error)
This approach reduces repeated code when multiple exceptions can be handled in the same way. Use separate handlers when different exceptions require different recovery actions.
18. Exception Chaining
Exception chaining preserves the relationship between an original exception and a new exception raised while handling it. This is useful when translating a low-level failure into a more meaningful application-level error.
Example
def load_age(text):
try:
return int(text)
except ValueError as error:
raise RuntimeError("Unable to process the age value") from error
try:
load_age("unknown")
except RuntimeError as error:
print("Application error:", error)
print("Original cause:", error.__cause__)
Output:
Application error: Unable to process the age value
Original cause: invalid literal for int() with base 10: 'unknown'
The from error expression explicitly records the original exception as the cause of the new exception. This helps preserve useful diagnostic information.
19. Common Mistakes in Exception Handling
Mistake 1: Using a Bare Except Clause Everywhere
try:
result = 10 / 0
except:
print("Something went wrong.")
A bare except catches exceptions beyond ordinary application errors, including some termination-related exceptions. Prefer catching specific exception types when possible.
Mistake 2: Catching Exception Without a Clear Reason
try:
number = int("hello")
except Exception:
print("Error")
This may hide the distinction between different failures. Use except ValueError when invalid conversion is the expected failure.
Mistake 3: Ignoring Exceptions
try:
result = 10 / 0
except ZeroDivisionError:
pass
Silently ignoring an exception can make a program appear successful even when an operation has failed. Only suppress an exception when the failure is genuinely safe to ignore.
Mistake 4: Placing Too Much Code Inside try
A large try block may catch exceptions from statements unrelated to the operation being protected. Keep the protected section focused on the statements that may reasonably raise the exceptions you intend to handle.
Mistake 5: Misunderstanding Logical Errors
Exception handling does not automatically detect incorrect formulas or algorithms. Logical errors still require testing, debugging, validation, and careful review of the program's requirements.
20. Best Practices for Error and Exception Handling
- Understand the cause of an error before attempting to fix it.
- Read the traceback carefully, especially the final exception line and relevant source locations.
- Catch specific exceptions whenever possible.
- Use
else to separate successful processing from exception handling.
- Use
finally for cleanup when appropriate.
- Use
with for resources such as files that support context management.
- Validate user input before performing sensitive calculations or operations.
- Raise appropriate exceptions when a function cannot satisfy its contract.
- Preserve the original cause when converting exceptions.
- Avoid silently ignoring unexpected failures.
- Record useful diagnostic information without exposing secrets or sensitive data.
- Test both successful and failing execution paths.
21. Practical Example: Student Marks Validation
This example demonstrates how to handle invalid numeric input and validate marks before calculating a result.
def calculate_result(marks):
if marks < 0 or marks > 100:
raise ValueError("Marks must be between 0 and 100")
if marks >= 40:
return "Pass"
return "Fail"
try:
marks = int(input("Enter student marks: "))
result = calculate_result(marks)
except ValueError as error:
print("Invalid marks:", error)
else:
print("Student result:", result)
finally:
print("Result processing completed.")
Example output for input 85:
Enter student marks: 85
Student result: Pass
Result processing completed.
Example output for input 120:
Enter student marks: 120
Invalid marks: Marks must be between 0 and 100
Result processing completed.
The same ValueError handler covers both invalid integer conversion and invalid marks. In a larger application, separate validation exception classes may be appropriate if these situations need different responses.
22. Practical Example: Safe File Handling
Files may be unavailable because they do not exist, access is denied, or an operating system operation fails. Exception handling allows the program to respond to these conditions.
try:
with open("student_data.txt", "r", encoding="utf-8") as file:
content = file.read()
except FileNotFoundError:
print("The requested file does not exist.")
except PermissionError:
print("Permission denied while opening the file.")
except OSError as error:
print("File operation failed:", error)
else:
print("File contents:")
print(content)
The with statement manages the file's lifecycle and ensures that it is closed when control leaves the block. The exception handlers address common file access failures without treating all errors as identical.
23. Mini Project: Simple Calculator with Exception Handling
Objective: Build a calculator that accepts two numbers and an arithmetic operator while handling invalid input and division by zero.
Requirements
- Accept two numeric inputs.
- Support addition, subtraction, multiplication, and division.
- Handle non-numeric input.
- Handle division by zero.
- Display a meaningful message for unsupported operators.
- Use
else to display a successful result.
Sample Implementation
def calculator(first, second, operator):
if operator == "+":
return first + second
elif operator == "-":
return first - second
elif operator == "*":
return first * second
elif operator == "/":
if second == 0:
raise ZeroDivisionError("Cannot divide by zero")
return first / second
else:
raise ValueError("Unsupported operator")
try:
first = float(input("Enter first number: "))
second = float(input("Enter second number: "))
operator = input("Enter operator (+, -, *, /): ")
result = calculator(first, second, operator)
except ValueError as error:
print("Input error:", error)
except ZeroDivisionError as error:
print("Calculation error:", error)
else:
print("Result:", result)
finally:
print("Calculator operation completed.")
Example output:
Enter first number: 10
Enter second number: 0
Enter operator (+, -, *, /): /
Calculation error: Cannot divide by zero
Calculator operation completed.
Project extension: Add a calculation history, support exponentiation, and write unit tests for valid calculations and each error condition.
24. Practice Exercises
Exercise 1: Safe Integer Conversion
Write a program that converts a user-provided string into an integer and handles invalid input using ValueError.
Exercise 2: Division Calculator
Accept two numbers and perform division. Display a suitable message when the divisor is zero.
Exercise 3: List Index Validation
Create a list of five items and ask the user for an index. Handle invalid indexes using IndexError.
Exercise 4: Dictionary Lookup
Create a dictionary containing student names and marks. Handle missing keys using KeyError.
Exercise 5: File Reader
Open a text file and display its contents. Handle a missing file and other relevant file access errors.
Exercise 6: Age Validation
Create a function that accepts an age and raises ValueError when the age is negative.
Exercise 7: Exception Cleanup
Write a program that uses try, except, else, and finally to demonstrate successful and unsuccessful operations.
25. Interview Questions and Answers
Q1. What is an error in Python?
Answer: An error is a problem that prevents code from executing correctly or producing its intended result. It may be caused by invalid syntax, a runtime exception, or incorrect logic.
Q2. What is an exception?
Answer: An exception is an object raised to represent a problem encountered during program execution.
Q3. What is the difference between a syntax error and an exception?
Answer: A syntax error prevents Python from parsing the code, while an exception occurs when an operation fails during execution.
Q4. What is a logical error?
Answer: A logical error occurs when a program runs but produces an incorrect result because its algorithm or formula is wrong.
Q5. What is the purpose of try and except?
Answer: The try block contains code that may raise an exception, and the except block handles a matching exception.
Q6. What is the purpose of finally?
Answer: The finally block executes when control leaves the associated exception-handling construct and is commonly used for cleanup.
Q7. When does the else clause execute?
Answer: It executes when the try block completes without raising an exception.
Q8. What does the raise statement do?
Answer: It explicitly raises an exception to signal that an operation cannot continue normally.
Q9. What is a traceback?
Answer: A traceback provides diagnostic information about the call sequence and source locations associated with an exception.
Q10. What is the difference between TypeError and ValueError?
Answer: A TypeError generally indicates an inappropriate type for an operation, while a ValueError indicates that a value is inappropriate for an operation even though its type may be acceptable.
Q11. Why should specific exceptions be caught?
Answer: Specific handlers make failures easier to diagnose and reduce the risk of hiding unrelated errors.
Q12. What is exception chaining?
Answer: Exception chaining preserves the relationship between an original exception and another exception raised while handling it.
Q13. What is the purpose of the with statement?
Answer: The with statement manages resources through a context manager and supports reliable cleanup, such as closing files.
Q14. Can logical errors be handled automatically with try and except?
Answer: No. Logical errors often do not raise exceptions. They must be identified through testing, debugging, validation, and reviewing the algorithm.
26. Quick Revision Notes
- Syntax errors occur when code violates Python grammar.
- Runtime exceptions occur when operations fail during execution.
- Logical errors produce incorrect results even when code runs.
- Built-in exceptions include
TypeError, ValueError, NameError, and ZeroDivisionError.
- A traceback helps identify where an exception occurred.
try identifies statements that may fail.
except handles matching exceptions.
else runs when the try block succeeds.
finally supports cleanup during normal or exceptional exits.
raise explicitly signals an exception.
- Specific exception handling is usually better than a bare
except.
- The
with statement is useful for safe resource management.
27. Final Checklist
- Understand the different types of programming errors.
- Recognize common built-in exceptions.
- Read and interpret tracebacks.
- Use
try and except correctly.
- Apply multiple exception handlers where needed.
- Understand the difference between
else and finally.
- Raise and re-raise exceptions appropriately.
- Understand basic exception inheritance and chaining.
- Practice handling errors in calculators, file readers, and validation functions.
- Test both successful operations and expected failure conditions.
Conclusion
Errors and exceptions are fundamental to writing reliable Python programs. Understanding syntax errors, runtime exceptions, and logical errors helps developers identify the source of a problem and select the correct solution.
Python's exception-handling features make it possible to handle expected failures, validate input, protect important operations, and manage resources safely. By practicing try, except, else, finally, and raise, you can develop more robust and maintainable applications.
Learn More with JustAcademy
Explore the Python Training Course to strengthen your programming fundamentals, debugging skills, and understanding of exception handling.
Register for a Course Demo to learn more about the available training options.
Visit JustAcademy to explore additional courses and learning resources.